package erfgame.core.world.terrain.insertion;

import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;


import erfgame.core.graphics.renderer.ImageEntityRenderer;
import erfgame.core.graphics.renderer.chain.RendererChain;
import erfgame.core.world.terrain.BlockSurfaceImages;
import erfgame.core.world.terrain.PixelDepth;
import erfgame.core.world.terrain.SurfaceImage;
@SuppressWarnings(value="serial")
public class SurfaceTerrainImageInsertion 
	extends AbstractSurfaceInsertion {
	private transient BlockSurfaceImages blockSurfaceImages;
	private transient SurfaceImage surfaceImage;
	private transient Rectangle bounds;
	private RendererChain rendererChain;
	
	public SurfaceTerrainImageInsertion() {
		
	}
	
	public SurfaceTerrainImageInsertion( BlockSurfaceImages images, SurfaceImage surfaceImage ) {
		setSurface( images, surfaceImage );
	}
		
	public void setSurface( BlockSurfaceImages images, SurfaceImage surfaceImage ) {
		this.surfaceImage = surfaceImage;
		this.bounds = new Rectangle( 
				surfaceImage.getPx(), 
				surfaceImage.getPy(), 
				surfaceImage.getImage().getWidth(), 
				surfaceImage.getImage().getHeight()
		);
		this.blockSurfaceImages = images;
		this.rendererChain = new RendererChain(
				new ImageEntityRenderer( surfaceImage.getImage(), new Point(), 0 )
		);
	}

	public Rectangle getBounds() {
		return this.bounds;
	}
	
	public int getDepth( Point p ) {
		// this should never be null if there is a surface associated with it
		int[][] surfaces = this.blockSurfaceImages.getSurfaces();
		int surfaceId = surfaces[p.x][p.y];
		if( surfaceId == this.surfaceImage.getSurfaceId() ) {
			// this should never be null if there is a surface image associated with it
			PixelDepth[][] depths = this.blockSurfaceImages.getPixelDepths();
			PixelDepth depth = depths[p.x][p.y];
			if( depth != null ) {
				return depth.getFirstDepthStart();
			} else {
				return -1;
			}
		} else {
			return -1;
		}
	}

	public int getDepth(Rectangle area) {
		int[][] surfaces = this.blockSurfaceImages.getSurfaces();
		// find a depth matching this surface in this area
		for( int x=area.width+area.x; x>area.x; ) {
			x--;
			int[] surfacesX = surfaces[x];
			// there is a good argument for starting at the top of the y, because 
			// most units stand on the ground it reduces equal results for a single sample
			for( int y=area.y; y<area.y+area.height; y++) {
				int surfaceId = surfacesX[y];
				if( surfaceId == this.surfaceImage.getSurfaceId() ) {
					// look up the depth
					PixelDepth[][] depths = this.blockSurfaceImages.getPixelDepths();
					PixelDepth depth = depths[x][y];
					if( depth != null) {
						return depth.getFirstDepthStart();
					}
				}
			}
		}
		return -1;
	}

	public void render(Graphics g, boolean isTop) {
		this.rendererChain.getHead().render(g, this.bounds.x, this.bounds.y);
	}

//	@Override
//	public int getOrder(SurfaceInsertion renderer) {
//		if( renderer instanceof SurfaceTerrainImageInsertion ) {
//			// these never overlap
//			return ORDER_DONT_CARE;
//		} else {
//			return super.getOrder(renderer);
//		}
//	}
	
	public SurfaceImage getSurfaceImage() {
		return this.surfaceImage;
	}

	public RendererChain getRendererChain() {
		return this.rendererChain;
	}
}
